package sgsi.controller.dao.impl;

import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import sgsi.controller.dao.PaletDao;
import sgsi.model.alocacion.EstadoEnum;
import sgsi.model.entidades.Palet;

public class PaletDaoHibernateImpl extends HibernateDaoSupport implements
		PaletDao {

	private static final String BUSCAR_POR_CODIGOS = "select p from Palet p where p.estado in ('Alocado', 'Creado') and p.codigoPalet in ";
	private static final String BUSCAR_POR_CODIGO = "select p from Palet p where p.estado in ('Alocado', 'Creado') and p.codigoPalet = ?";
	private static final String BUSCAR_POR_CLIENTE = "select p from Palet p where p.estado in ('Alocado', 'Creado') and p.cliente.codigoCliente = ?";
	private static final String OPERADOR_TAG = "<OPERADOR>";
	private static final String BUSQUEDA_GENERAL = "select p from Palet p where p.estado in (" + OPERADOR_TAG + ") ";
	private static final String CODIGO_ARTICULO_QUERY = OPERADOR_TAG +" p.articulo.codigoArticulo = ";
	private static final String CODIGO_TIPO_ARTICULO_QUERY = OPERADOR_TAG +" p.tipoDePalet.codigoTipoDePalet = ";
	private static final String CODIGO_CLIENTE_QUERY = OPERADOR_TAG +" p.cliente.codigoCliente = ";
	private static final String CODIGO_ALMACEN_QUERY = OPERADOR_TAG +" p.ubicacion.area.almacen.codigoAlmacen = ";
	private static final String CODIGO_AREA_QUERY = OPERADOR_TAG +" p.ubicacion.area.codigoArea = ";
	private static final String CODIGO_UBICACION_QUERY = OPERADOR_TAG +" p.ubicacion.codigoUbicacion = ";
	private static final String BUSCAR_POR_TIPO_DE_PALET = "select p from Palet p where p.estado in ('Alocado', 'Creado') and p.tipoDePalet.codigoTipoDePalet = ?";
	private static final String BUSCAR_POR_ARTICULO = "select p from Palet p where p.estado in ('Alocado', 'Creado') and p.articulo.codigoArticulo = ?";
	private static final String BUSCAR_POR_TIPO_DE_ARTICULO = "select p from Palet p where p.estado in ('Alocado', 'Creado') and p.articulo.tipoDeArticulo.codigoTipoDeArticulo = ?";
	private static final String BUSCAR_POR_UBICACION = "select p from Palet p where p.estado in ('Alocado', 'Creado') and p.ubicacion.codigoUbicacion = ?";
	
	@SuppressWarnings("unchecked")
	public List<Palet> obtenerPorUbicacion(int codigoUbicacion) {
		return getHibernateTemplate().find(BUSCAR_POR_UBICACION, codigoUbicacion);		
	}
	
	@SuppressWarnings("unchecked")
	public List<Palet> obtenerPorTipoDePalet(int codigoTipoDePalet) {
		return getHibernateTemplate().find(BUSCAR_POR_TIPO_DE_PALET, codigoTipoDePalet);		
	}

	@SuppressWarnings("unchecked")
	public List<Palet> obtenerPorArticulo(int codigoArticulo) {
		return getHibernateTemplate().find(BUSCAR_POR_ARTICULO, codigoArticulo);		
	}
	
	@SuppressWarnings("unchecked")
	public List<Palet> obtenerPorTipoDeArticulo(int codigoTipoDeArticulo) {
		return getHibernateTemplate().find(BUSCAR_POR_TIPO_DE_ARTICULO, codigoTipoDeArticulo);		
	}
	
	public Palet guardar(Palet palet) {
		getHibernateTemplate().saveOrUpdate(palet);
		return palet;
	}

	@SuppressWarnings("unchecked")
	public List<Palet> obtenerPaletsPorId(String[] codigos) {
		StringBuffer query = new StringBuffer(BUSCAR_POR_CODIGOS);
		query.append("(");
		for (int i = 0; i < codigos.length; i++) {
			query.append("'").append(codigos[i]).append("'");
			if (i != codigos.length - 1) {
				query.append(",");
			}
		}
		query.append(")");
		return getHibernateTemplate().find(query.toString());
	}

	public List<Palet> guardar(List<Palet> palets) {
		for (Palet palet : palets) {
			guardar(palet);
		}

		return palets;
	}

	@SuppressWarnings("unchecked")
	public Palet obtenerPorCodigo(int codigo) {
		List palets = getHibernateTemplate().find(BUSCAR_POR_CODIGO, codigo);
		if (palets.isEmpty()) {
			return null;
		}
		return (Palet) palets.get(0);
	}

	public void eliminar(Palet palet) {
		getHibernateTemplate().delete(palet);
	}

	@SuppressWarnings("unchecked")
	public List<Palet> buscarPalet(String codigoArticulo, String estado,
			String codigoTipoArticulo, String codigoCliente, String fechaDesde,
			String fechaHasta, String codigoAlmacen, String codigoArea, String codigoUbicacion) {
		
		String estadoStr = (StringUtils.isNotBlank(estado)) ? "'" + estado + "'" : obtenerTodosLosEstados();
		String query = BUSQUEDA_GENERAL.replace(OPERADOR_TAG, estadoStr);
		query += nullSafeLike(codigoArticulo, CODIGO_ARTICULO_QUERY);
		query += nullSafeLike(codigoTipoArticulo, CODIGO_TIPO_ARTICULO_QUERY);
		query += nullSafeLike(codigoCliente, CODIGO_CLIENTE_QUERY);
		query += nullSafeLike(codigoAlmacen, CODIGO_ALMACEN_QUERY);
		query += nullSafeLike(codigoArea, CODIGO_AREA_QUERY);
		query += nullSafeLike(codigoUbicacion, CODIGO_UBICACION_QUERY);
		query += nullSafeLikeFechas(fechaDesde, fechaHasta);
		query = query.replaceAll(OPERADOR_TAG, " and ");
		return getHibernateTemplate().find(query);
	}

	private String obtenerTodosLosEstados() {
		List<EstadoEnum> estados = EstadoEnum.getEstadosValidosCombo();
		StringBuffer resultado = new StringBuffer();
		for (int i = 0; i < estados.size(); i++) {
			resultado.append("'").append(estados.get(i).getEstado()).append("'");
			if (i != (estados.size() - 1)){
				resultado.append(" , ");
			}
		}
		return resultado.toString();
	}

	private String nullSafeLikeFechas(String fechaDesde, String fechaHasta) {
		StringBuffer result = new StringBuffer(" ");

		if (StringUtils.isNotBlank(fechaDesde)) {
			result.append(OPERADOR_TAG +" p.fechaDeVencimiento > '" + fechaDesde + "'");
		}

		if (StringUtils.isNotBlank(fechaHasta)) {
			result.append(OPERADOR_TAG +" p.fechaDeVencimiento < '" + fechaHasta + "'");
		}

		return result.toString();
	}

	private String nullSafeLike(String valor, String queryBase) {
		return (StringUtils.isNotBlank(valor)) ? queryBase +  valor : "";
	}
	

	@SuppressWarnings("unchecked")
	public List<Palet> obtenerPorCliente(int codigoCliente) {
		return getHibernateTemplate().find(BUSCAR_POR_CLIENTE, codigoCliente);
	}

}
